﻿/**
 * Copyright (C) 2014-2050 SOUI团队
 * All rights reserved.
 *
 * @file       stabctrl.h
 * @brief
 * @version    v1.0
 * @author     soui
 * @date       2014-07-06
 *
 * Describe    SOUI应用程序入口
 */

#pragma once
#include "core/ssingleton.h"
#include "unknown/obj-ref-impl.hpp"
#include "interface/SRender-i.h"
#include "interface/SScriptModule-i.h"
#include "interface/STranslator-i.h"
#include "interface/STooltip-i.h"
#include "interface/SLog-i.h"
#include "interface/SAttrStorage-i.h"
#include "interface/SInterpolator-i.h"
#include "interface/SAnimation-i.h"
#include "interface/SValueAnimator-i.h"
#include "control/SRealWndHandler-i.h"
#include "res.mgr/SResProvider.h"
#include "res.mgr/SNamedValue.h"
#include "helper/SAutoBuf.h"
#include "unknown/obj-ref-impl.hpp"
#include "res.mgr/SObjDefAttr.h"
#include "helper/SCriticalSection.h"
#include  "helper/SAutoBuf.h"
#include "core/smsgloop.h"
#include "core/SObjectFactory.h"
#include <OleAcc.h>
#include "interface/SRender-i.h"
#include "interface/SAnimation-i.h"
#include "interface/SSkinobj-i.h"
#include "res.mgr/SSkinPool.h"
#include <memory>
#include <map>

#define GETRESPROVIDER      SOUI::SApplication::getSingletonPtr()
#define GETRENDERFACTORY    SOUI::SApplication::getSingleton().GetRenderFactory()
#define GETREALWNDHANDLER   SOUI::SApplication::getSingleton().GetRealWndHander()
#define GETTOOLTIPFACTORY   SOUI::SApplication::getSingleton().GetToolTipFactory()

#define LOADXML(p1,p2)      SOUI::SApplication::getSingleton().LoadXmlDocment(p1,p2)
#define LOADIMAGE(p1,p2)    SOUI::SApplication::getSingleton().LoadImage(p1,p2)
#define LOADIMAGE2(p1)      SOUI::SApplication::getSingleton().LoadImage2(p1)
#define LOADICON(p1,p2)     SOUI::SApplication::getSingleton().LoadIcon(p1,p2,p2)
#define LOADICON2(p1)       SOUI::SApplication::getSingleton().LoadIcon2(p1)
#define TR(p1,p2)           SOUI::SApplication::getSingleton().tr(p1,p2)
#define STR2ID(p1)          SOUI::SApplication::getSingleton().Str2ID(p1)

#define GETCOLOR(x)         SOUI::SApplication::getSingleton().GetColor(x)
#define GETSTRING(x)        SOUI::SApplication::getSingleton().GetString(x)
#define GETLAYOUTSIZE(x)    SOUI::SApplication::getSingleton().GetLayoutSize(x)

#define CREATEINTERPOLATOR(x)  SOUI::SApplication::getSingleton().CreateInterpolatorByName(x)


#define GETSKIN(p1,scale) SOUI::SApplication::getSingleton().GetSkin(p1,scale)
#define GETBUILTINSKIN(p1) SOUI::SApplication::getSingleton().GetBuiltinSkin(p1,100)
#define GETBUILTINSKIN2(p1,scale) SOUI::SApplication::getSingleton().GetBuiltinSkin(p1,scale)
#define GETSKINPOOLMGR SOUI::SApplication::getSingletonPtr()

#define GETTEMPLATEPOOLMR SOUI::STemplatePoolMgr::getSingletonPtr()

namespace SOUI {
    struct IAccProxy;
    interface IMsgLoopFactory : public IObjRef {
        virtual SMessageLoop *CreateMsgLoop() = 0;
        virtual void DestoryMsgLoop(SMessageLoop *pMsgLoop) = 0;
    };
    
    interface SOUI_EXP ISystemObjectRegister {
        virtual void RegisterLayouts(SObjectFactoryMgr *objFactory) const {}
        virtual void RegisterSkins(SObjectFactoryMgr *objFactory)  const {}
        virtual void RegisterWindows(SObjectFactoryMgr *objFactory)  const {}
        virtual void RegisterInterpolator(SObjectFactoryMgr *objFactory) const {}
        virtual void RegisterAnimation(SObjectFactoryMgr *objFactory) const {}
        virtual void RegisterValueAnimator(SObjectFactoryMgr *objFactory) const {}
    };
    
    class SOUI_EXP SObjectDefaultRegister : public ISystemObjectRegister {
      public:
        void RegisterWindows(SObjectFactoryMgr *objFactory) const;
        void RegisterSkins(SObjectFactoryMgr *objFactory) const;
        void RegisterLayouts(SObjectFactoryMgr *objFactory) const;
        void RegisterInterpolator(SObjectFactoryMgr *objFactory) const;
        void RegisterAnimation(SObjectFactoryMgr *objFactory) const;
        void RegisterValueAnimator(SObjectFactoryMgr *objFactory) const;
    };
    
    /**
     * @class     SApplication
     * @brief     SOUI Application
     *
     * Describe   SOUI Application
     */
    class SOUI_EXP SApplication : public SSingleton<SApplication>, public SObjectFactoryMgr {
      public:
        /**
         * SApplication
         * @brief    构造函数
         * @param    IRenderFactory * pRendFactory --  渲染模块
         * @param    HINSTANCE hInst --  应用程序句柄
         * @param    LPCTSTR pszHostClassName --  使用SOUI创建窗口时默认的窗口类名
         * @param    ISystemObjectRegister *pSysObjRegister -- 系统控件注册器
         *
         * Describe
         */
        SApplication(IRenderFactory *pRendFactory, HINSTANCE hInst, LPCTSTR pszHostClassName = _T("SOUIHOST"),
                     const ISystemObjectRegister &sysObjRegister = SObjectDefaultRegister(), BOOL bImeApp = FALSE);
                     
        ~SApplication(void);
        
        
        /**
         * GetInstance
         * @brief    获得应用程序句柄
         * @return   HINSTANCE
         *
         * Describe
         */
        HINSTANCE GetInstance();
        
        
        /**
         * Init
         * @brief    从数组里初始化命名ID列表
         * @param    SNamedID::NAMEDVALUE *pValue --  数组
         * @param    int nCount --  数组长度
         * @param    BOOL bSorted -- 数组关键字从小到大已经有序
         *
         * Describe  SNamedID::NAMEDVALUE应该是由uiresbuilder自动生成的列表数据，不要手动修改
         */
        void InitXmlNamedID(const SNamedID::NAMEDVALUE *pNamedValue, int nCount, BOOL bSorted);
        
        /**
         * LoadXmlDocment
         * @brief    从资源中加载一个XML Document。
         * @param [out] pugi::xml_document & xmlDoc --  输出的xml_document对象
         * @param    const SStringT & strResId --  XML文件在资源中的type:name
         * @return   BOOL true-加载成功, false-加载失败
         *
         * Describe
         */
        BOOL LoadXmlDocment(pugi::xml_document &xmlDoc, const SStringT &strResId);
        
        BOOL LoadBuffer(SAutoBuf &buffer, const SStringT &strResId);
        
        IAnimation *LoadAnimation(const SStringT &strResId);
        
        IValueAnimator *LoadValueAnimator(const SStringT &strResId);
        /**
         * GetRenderFactory
         * @brief    获得当前的渲染模块
         * @return   IRenderFactory * 渲染模块指针
         *
         * Describe
         */
        IRenderFactory *GetRenderFactory();
        
        /**
         * GetScriptModule
         * @brief    创建脚本模块对象
         * @param [out] IScriptModule **ppScriptModule -- 脚本模块对象
         * @return   HRESULT -- S_OK 创建成功
         *
         * Describe
         */
        HRESULT CreateScriptModule(IScriptModule **ppScriptModule);
        
        /**
         * SetScriptModule
         * @brief    设置SOUI中使用的脚本模块类厂
         * @param    IScriptFactory *pScriptModule --  脚本模块类厂
         * @return   void
         *
         * Describe
         */
        void SetScriptFactory(IScriptFactory *pScriptModule);
        
        
        /**
         * GetTranslator
         * @brief    获取语言翻译模块
         * @return   ITranslator * 语言翻译模块指针
         *
         * Describe
         */
        ITranslatorMgr *GetTranslator();
        
        /**
         * SetTranslator
         * @brief    设置语言翻译模块
         * @param    ITranslator * pTrans --  语言翻译模块指针
         * @return   void
         *
         * Describe
         */
        void SetTranslator(ITranslatorMgr *pTrans);
        
        /**
         * GetRealWndHander
         * @brief    获得RealWndHander
         * @return   IRealWndHandler * -- RealWndHander
         * Describe
         */
        IRealWndHandler *GetRealWndHander();
        
        /**
         * SetRealWndHandler
         * @brief    设置RealWnd处理接口
         * @param    IRealWndHandler * pRealHandler --  RealWnd处理接口
         * @return   void
         * Describe
         */
        void SetRealWndHandler(IRealWndHandler *pRealHandler);
        
        /**
         * GetToolTipFactory
         * @brief    获取ToolTip处理接口
         * @return   IToolTipFactory * -- ToolTip处理接口
         * Describe
         */
        IToolTipFactory *GetToolTipFactory();
        
        /**
         * SetToolTipFactory
         * @brief    设置ToolTip处理接口
         * @param    IToolTipFactory * pToolTipFac --  ToolTip处理接口
         * @return   void --
         * Describe
         */
        void SetToolTipFactory(IToolTipFactory *pToolTipFac);
        
        BOOL SetMsgLoopFactory(IMsgLoopFactory *pMsgLoopFac);
        
        IMsgLoopFactory *GetMsgLoopFactory();
        
        void SetLogManager(ILog4zManager *pLogMgr);
        
        ILog4zManager *GetLogManager();
        
        void SetAttrStorageFactory(IAttrStorageFactory *pAttrStorageFactory);
        IAttrStorageFactory *GetAttrStorageFactory();
        
        /**
         * Run
         * @brief    启动SOUI的主消息循环
         * @param    HWND hMainWnd --  应用程序主窗口句柄
         * @return   int 消息循环结束时的返回值
         *
         * Describe
         */
        int Run(HWND hMainWnd);
        
        void SetAppDir(const SStringT &strAppDir);
        
        SStringT GetAppDir()const;
        
        HWND GetMainWnd();
        
        template<class T>
        bool RegisterWindowClass() {
            if (T::GetClassType() != Window) {
                return false;
            }
            return TplRegisterFactory<T>();
        }
        
        template<class T>
        bool UnregisterWindowClass() {
            if (T::GetClassType() != Window) {
                return false;
            }
            return TplUnregisterFactory<T>();
        }
        template<class T>
        bool RegisterSkinClass() {
            if (T::GetClassType() != Skin) {
                return false;
            }
            return TplRegisterFactory<T>();
        }
        
        template<class T>
        bool UnregisterSkinClass() {
            if (T::GetClassType() != Skin) {
                return false;
            }
            return TplUnregisterFactory<T>();
        }
        
        int Str2ID(const SStringW &str);
        
        SStringW tr(const SStringW &strSrc, const SStringW &strCtx)const;
        SWindow *CreateWindowByName(LPCWSTR pszWndClass);
        ISkinObj *CreateSkinByName(LPCWSTR pszSkinClass);
        IInterpolator *CreateInterpolatorByName(LPCWSTR pszName) ;
        IAnimation *CreateAnimationByName(LPCWSTR pszName) ;
        IValueAnimator *CreateValueAnimatorByName(LPCWSTR pszName) ;
        
        virtual IAccProxy *CreateAccProxy(SWindow *pWnd) const;
        virtual IAccessible *CreateAccessible(SWindow *pWnd) const;
        
        void *GetInnerSingleton(int nType);
        
        void NotifySkinChanged();
        
        
        bool SetTheme(const SOUI::SStringW &ssThemeName, const SOUI::SStringW &themeType);
        bool InitEnv(const SOUI::SStringW &envName, const SOUI::SStringW &themeType);
        
        BOOL    IsFileType(LPCTSTR pszType);
        IResProvider *GetMatchResProvider(LPCTSTR pszType, LPCTSTR pszResName);
        HICON   LoadIcon(LPCTSTR pszResName, int cx = 0, int cy = 0, BOOL bFromFile = FALSE);
        HCURSOR LoadCursor(LPCTSTR pszResName, BOOL bFromFile = FALSE);
        HBITMAP LoadBitmap(LPCTSTR pszResName, BOOL bFromFile = FALSE);
        IBitmap *LoadImage(LPCTSTR pszType, LPCTSTR pszResName);
        IImgX *LoadImgX(LPCTSTR pszType, LPCTSTR pszResName);
        //使用type:name形式的字符串加载图片
        IBitmap *LoadImage2(const SStringW &strImgID);
        //使用name:size形式的字符串加载图标，如果没有size,则默认系统图标SIZE
        HICON   LoadIcon2(const SStringW &strIconID);
        
        size_t GetRawBufferSize(LPCTSTR pszType, LPCTSTR pszResName);
        BOOL GetRawBuffer(LPCTSTR pszType, LPCTSTR pszResName, LPVOID pBuf, size_t size);
        
        //从字符串返回颜色值，字符串可以是：@color/red (red是在资源包中的颜色表定义的颜色名)，也可以是rgba(r,g,b,a)，也可以是rgb(r,g,b)，还可以是#ff0000(ff)这样的格式
        COLORREF GetColor(const SStringW &strColor);
        
        void updateColor(const SStringW &colorKey, COLORREF colorVal);
        
        //获取资源包中的颜色表中固定索引号的颜色，只支持从第一个资源包中查询
        COLORREF GetColor(int idx);
        
        //从字符串名返回字符串值，字符串可以是：@string/title (title是在资源包中的字符串表定义的命名字符串)
        SStringW GetString(const SStringW &strString);
        //获取资源包中的字符串表中固定索引号的字符串，只支持从第一个资源包中查询
        SStringW GetString(int idx);
        
        //从字符串名返回LayoutSize，字符串可以是：@dim/something (something是在资源包中的Dim表定义的命名字符串)
        SLayoutSize GetLayoutSize(const SStringW &strSize);
        SLayoutSize GetLayoutSize(int idx);
        
        pugi::xml_node GetCaretInfo();
        SObjDefAttr  *GetObjDefAttr();
        
        
        /**
        * GetSkin
        * @brief    获得与指定name匹配的SkinObj
        * @param    LPCWSTR strSkinName --    Name of Skin Object
        * @return   ISkinObj*  -- 找到的Skin Object
        * Describe
        */
        
        bool addGlobalSkin(const SStringW &strSkinName, ISkinObj *pSkin, int nScale);
        
        ISkinObj *GetSkin(const SStringW &strSkinName, int nScale);
        ISkinObj *GetBuiltinSkin(SYS_SKIN uID, int nScale);
        ISkinObj *GetBuiltinSkin(const SStringW &strSkinName, int nScale);
      public:
        // Message loop map methods
        bool AddMsgLoop(SMessageLoop *pMsgLoop);
        
        bool RemoveMsgLoop();
        
        SMessageLoop *GetMsgLoop(DWORD dwThreadID = ::GetCurrentThreadId()) const;
        
        COLORREF    GetDefTextColor();
        COLORREF    GetDefTextGrayColor();
      protected:
        virtual void RegisterSystemObjects() {}
        
        void _CreateSingletons(HINSTANCE hInst, LPCTSTR pszHostClassName, BOOL bImeApp);
        void _DestroySingletons();
        BOOL _LoadXmlDocment(LPCTSTR pszXmlName, LPCTSTR pszType, pugi::xml_document &xmlDoc,
                             IResProvider *pResProvider = NULL);
                             
        SAutoRefPtr<IRealWndHandler>    m_pRealWndHandler;
        SAutoRefPtr<IScriptFactory>     m_pScriptFactory;
        SAutoRefPtr<IRenderFactory>     m_RenderFactory;
        SAutoRefPtr<ITranslatorMgr>     m_translator;
        SAutoRefPtr<IToolTipFactory>    m_tooltipFactory;
        SAutoRefPtr<IMsgLoopFactory>    m_msgLoopFactory;
        SAutoRefPtr<ILog4zManager>      m_logManager;   //log manager
        SAutoRefPtr<IAttrStorageFactory> m_pAttrStroageFactory;
        
        SNamedID                        m_namedID;
        
        SStringT    m_strAppDir;
        HINSTANCE   m_hInst;
        HWND        m_hMainWnd;
        
        mutable SCriticalSection    m_cs;
        SMap<DWORD, SMessageLoop * > m_msgLoopMap;
        SMessageLoop        *m_pMsgLoop;
        //一组单例指针
        void *m_pSingletons[SINGLETON_COUNT];
        
        SAutoRefPtr <IResProvider> m_pEnvResProvider;
        
        std::map<SOUI::SStringW, SAutoRefPtr <IResProvider>>    m_themeProviders;
        SAutoRefPtr <IResProvider> m_pCurThemeResProvider = nullptr;
        std::map <SOUI::SStringW, HCURSOR>  m_mapCachedCursor;
        
        std::map <SOUI::SStringW, std::shared_ptr <XSkinPool>>  m_mapSkinPool;
        std::shared_ptr <XSkinPool> m_pCurSkinPool = nullptr;
        
        XSkinPool       m_globalSkinPool;
        
        SNamedColor     m_namedColor;
        SNamedString    m_namedString;
        SNamedDimension m_namedDim;
        FontInfo        defFontInfo;
        pugi::xml_document xmlCaret;
        SAutoRefPtr <SObjDefAttr>  m_objDefAttr;
        
        COLORREF        m_colorTextDef = 0;
        COLORREF        m_colorTextGrayDef = 0;
    };
    
    
    
}//namespace SOUI